import sys
import cv2
import pyaudio
import wave
import os
import threading
import numpy as np
from moviepy import VideoFileClip, AudioFileClip
from PyQt5.QtCore import QTimer, QTime, Qt, QRect, QPoint,QSize, pyqtSignal
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QMessageBox, QFileDialog, QHBoxLayout, QVBoxLayout, QDialog, QShortcut, QMenu, QAction, QMainWindow
from PyQt5.QtGui import QIcon, QKeySequence, QPainter, QPen, QPixmap, QImage, QColor, QLinearGradient, QPainterPath
import pyautogui
from moviepy import concatenate_videoclips, CompositeAudioClip
import json
import keyboard  # 添加到文件顶部的导入语句中
from PIL import Image, ImageEnhance
import io
from PyQt5.QtCore import QBuffer

# 定义常量
AUDIO_FILENAME = 'recorded_audio.wav'
VIDEO_FILENAME = 'recorded_video.mp4'
CHUNK = 1024
sample_format = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
FPS = 15
class ScreenRecorderUI(QWidget):
    # 添加信号
    start_recording_signal = pyqtSignal()
    stop_recording_signal = pyqtSignal()
    # 添加信号用于快捷键动作
    shortcut_action_signal = pyqtSignal(str)
    
    def __init__(self):
        super().__init__()

        # 修改窗口标题
        self.setWindowTitle('CaptureFlow')
        self.setWindowIcon(QIcon('icon.png'))  # 请确保有一个icon.png文件
        self.setStyleSheet("background-color: black;")

        # 创建按钮
        self.capture_screen_button = QPushButton('屏幕截取', self)
        self.full_screen_button = QPushButton('全屏录制', self)
        self.screenshot_button = QPushButton('区域录制', self)
        self.game_button = QPushButton('游戏录制', self)
        self.more_button = QPushButton('设置', self)
        

        # 设置按钮样式
        button_style = """
        QPushButton {
            background-color: #444;
            color: white;
            border: none;
            width: 100px;
            height: 50px;
            font-size: 14px;
        }
        QPushButton:hover {
            background-color: #666;
        }
        """
        self.capture_screen_button.setStyleSheet(button_style)
        self.full_screen_button.setStyleSheet(button_style)
        self.screenshot_button.setStyleSheet(button_style)
        self.game_button.setStyleSheet(button_style)
        self.more_button.setStyleSheet(button_style)

        # 创建布局并添加按钮
        layout = QHBoxLayout()
        layout.addWidget(self.capture_screen_button)
        layout.addWidget(self.full_screen_button)
        layout.addWidget(self.screenshot_button)
        layout.addWidget(self.game_button)
        layout.addWidget(self.more_button)
        self.setLayout(layout)
        self.setFixedSize(450, 100)

        # 连接按钮点击事件
        self.capture_screen_button.clicked.connect(self.open_capture_dialog)
        self.full_screen_button.clicked.connect(self.open_full_screen_window)
        self.more_button.clicked.connect(self.open_settings_window)
        self.screenshot_button.clicked.connect(self.open_screenshot_window)
        self.game_button.clicked.connect(self.open_game_recording)

        # 将快捷键初始化移到最后
        self.shortcuts = {}
        # 使用 QTimer 延迟加载快捷键
        QTimer.singleShot(100, self.load_and_apply_shortcuts)

        # 添加一个属性来存储当前活动的录制窗口
        self.active_recording_window = None

        # 连接信号到槽
        self.start_recording_signal.connect(self._start_recording)
        self.stop_recording_signal.connect(self._stop_recording)
        self.shortcut_action_signal.connect(self.handle_shortcut_action)

    def load_and_apply_shortcuts(self):
        """加载并应用快捷键设置"""
        try:
            config_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'shortcuts.json')
            if os.path.exists(config_file):
                with open(config_file, 'r', encoding='utf-8') as f:
                    shortcuts_data = json.load(f)
                    
                # 清除现有快捷键
                for key in self.shortcuts:
                    try:
                        keyboard.remove_hotkey(self.shortcuts[key])
                    except:
                        pass
                self.shortcuts.clear()
                
                # 设置新的快捷键
                for key, shortcut_text in shortcuts_data.items():
                    # 转换 PyQt 快捷键格式为 keyboard 库格式
                    hotkey = shortcut_text.replace('Ctrl', 'ctrl').replace('Alt', 'alt').replace('Shift', 'shift')
                    
                    # 使用 lambda 来捕获当前的 key 值
                    keyboard.add_hotkey(hotkey, lambda k=key: self.shortcut_action_signal.emit(k))
                    
                    self.shortcuts[key] = hotkey
                    
        except Exception as e:
            print(f"加载快捷键设置失败: {str(e)}")

    def handle_shortcut_action(self, action_key):
        """在主线程中处理快捷键动作"""
        try:
            if action_key == 'capture_screen':
                self.open_capture_dialog()
            elif action_key == 'full_screen':
                self.open_full_screen_window()
            elif action_key == 'area_record':
                self.open_screenshot_window()
            elif action_key == 'game_record':
                self.open_game_recording()
            elif action_key == 'start_record':
                self.trigger_recording_action('start')
            elif action_key == 'stop_record':
                self.trigger_recording_action('stop')
        except Exception as e:
            print(f"处理快捷键动作失败: {str(e)}")

    def trigger_recording_action(self, action):
        """触发录制动作"""
        try:
            if action == 'start':
                # 发射信号而不是直接调用方法
                self.start_recording_signal.emit()
            elif action == 'stop':
                # 发射信号而不是直接调用方法
                self.stop_recording_signal.emit()
        except Exception as e:
            print(f"触发录制动作失败: {str(e)}")

    def _start_recording(self):
        """在主线程中处理开始录制"""
        try:
            # 检查全屏录制窗口
            if hasattr(self, 'full_screen_window') and self.full_screen_window.isVisible():
                self.active_recording_window = self.full_screen_window
            # 检查区域录制窗口
            elif hasattr(self, 'screenshot_window') and self.screenshot_window.isVisible():
                self.active_recording_window = self.screenshot_window
            
            # 如果有活动的录制窗口，执行开始录制
            if self.active_recording_window:
                self.active_recording_window.start_recording()
        except Exception as e:
            print(f"开始录制失败: {str(e)}")

    def _stop_recording(self):
        """在主线程中处理停止录制"""
        try:
            # 检查全屏录制窗口
            if hasattr(self, 'full_screen_window') and self.full_screen_window.isVisible():
                self.active_recording_window = self.full_screen_window
            # 检查区域录制窗口
            elif hasattr(self, 'screenshot_window') and self.screenshot_window.isVisible():
                self.active_recording_window = self.screenshot_window
            
            # 如果有活动的录制窗口，执行停止录制
            if self.active_recording_window:
                self.active_recording_window.stop_recording()
        except Exception as e:
            print(f"停止录制失败: {str(e)}")

    def open_full_screen_window(self):
        self.full_screen_window = FullScreenWindow()
        self.active_recording_window = self.full_screen_window
        self.full_screen_window.show()

    def open_settings_window(self):
        self.settings_window = SettingsWindow()
        self.settings_window.show()

    def open_screenshot_window(self):
        self.screenshot_window = ScreenshotWindow()
        self.active_recording_window = self.screenshot_window
        self.screenshot_window.show()

    def open_game_recording(self):
        self.open_full_screen_window()
        self.full_screen_window.showMinimized()  # 最小化全屏录制窗口
        self.showMinimized()  # 最小化主窗口

        # 设置快捷键
        self.start_shortcut = QShortcut(QKeySequence("Ctrl+Alt+R"), self.full_screen_window)
        self.start_shortcut.activated.connect(self.full_screen_window.start_recording)

        self.stop_shortcut = QShortcut(QKeySequence("Ctrl+Alt+T"), self.full_screen_window)
        self.stop_shortcut.activated.connect(self.full_screen_window.stop_recording)

        # 显示快捷键提示信息，使用 HTML 标签设置文本颜色为红色
        QMessageBox.information(self, "戏录制", "<font color='red'>使用 Ctrl+Alt+R 开始录制，Ctrl+Alt+T 停止录制。</font>")

    def open_capture_dialog(self):
        self.capture_dialog = CaptureDialog(self)
        self.capture_dialog.exec_()

    def closeEvent(self, event):
        """关闭窗口时清理资源"""
        try:
            # 清除所有注册的快捷键
            for key in self.shortcuts:
                try:
                    keyboard.remove_hotkey(self.shortcuts[key])
                except:
                    pass
            self.shortcuts.clear()
            
            # 确保所有录制窗口都被关闭
            if hasattr(self, 'full_screen_window'):
                self.full_screen_window.close()
            if hasattr(self, 'screenshot_window'):
                self.screenshot_window.close()
            if hasattr(self, 'capture_dialog'):
                self.capture_dialog.close()
                
            # 确保录制已停止
            if hasattr(self, 'active_recording_window') and self.active_recording_window:
                try:
                    self.active_recording_window.recording = False
                    if hasattr(self.active_recording_window, 'audio_thread'):
                        self.active_recording_window.audio_thread.join(timeout=1)
                    if hasattr(self.active_recording_window, 'video_thread'):
                        self.active_recording_window.video_thread.join(timeout=1)
                except:
                    pass

            # 清理临时文件
            temp_files = [AUDIO_FILENAME, VIDEO_FILENAME]
            for file in temp_files:
                if os.path.exists(file):
                    try:
                        os.remove(file)
                    except:
                        pass
                        
            # 确保应用程序完全退出
            QApplication.quit()
            
        except Exception as e:
            print(f"关闭时出错: {str(e)}")
            
        super().closeEvent(event)

class SettingsWindow(QWidget):
    def __init__(self):
        super().__init__()

        self.setWindowTitle('设置')
        self.setFixedSize(300, 300)  # 增加窗口高度

        # 修改软件介绍文本
        self.info_label = QLabel('软件简介', self)
        self.info_label.setWordWrap(True)
        self.info_label.setText(
            "CaptureFlow 是一款功能强大的屏幕录制和截图工具。\n"
            "支持全屏录制、区域录制、游戏录制和截图等多功能。\n"
            "操作简单，快捷键便捷，是您的得力助手。"
        )

        self.save_path_button = QPushButton('选择保存路径', self)
        self.shortcut_button = QPushButton('设置快捷键', self)
        self.contact_button = QPushButton('联系作者', self)  # 新增联系作者按钮

        # 布局
        layout = QVBoxLayout()
        layout.addWidget(self.info_label)
        layout.addWidget(self.save_path_button)
        layout.addWidget(self.shortcut_button)
        layout.addWidget(self.contact_button)
        self.setLayout(layout)

        # 连接按钮事件
        self.save_path_button.clicked.connect(self.select_save_path)
        self.shortcut_button.clicked.connect(self.open_shortcut_settings)
        self.contact_button.clicked.connect(self.show_contact_info)

        # 读取保存路径
        self.save_path = self.load_save_path()

    def open_shortcut_settings(self):
        self.shortcut_dialog = ShortcutSettingsDialog(self)
        self.shortcut_dialog.exec_()

    def select_save_path(self):
        save_path = QFileDialog.getExistingDirectory(self, '选择保存路径')
        if save_path:
            QMessageBox.information(self, '路径选择', f'保存路径已设置为：\n{save_path}')
            self.save_path = save_path
            self.save_save_path(save_path)

    def save_save_path(self, path):
        with open('save_path.txt', 'w') as file:
            file.write(path)

    def load_save_path(self):
        if os.path.exists('save_path.txt'):
            with open('save_path.txt', 'r') as file:
                return file.read().strip()
        return ""

    def show_contact_info(self):
        """显示联系方式对话框"""
        contact_dialog = QDialog(self)
        contact_dialog.setWindowTitle('联系作者')
        contact_dialog.setFixedSize(500, 400)  # 进一步增加对话框大小
        
        # 创建标签显示联系信息
        contact_label = QLabel(contact_dialog)
        contact_label.setWordWrap(True)
        contact_label.setAlignment(Qt.AlignCenter)
        contact_label.setText(
            "<span style='font-size: 24px; font-weight: bold;'>关于作者:</span><br><br>"
            "<span style='font-size: 20px;'>"
            "我是一个业余的程序爱好者，<br>"
            "这是我自己使用的小作品。<br>"
            "如果您在使用过程中发现任何bug或问题，<br>"
            "都可以随时联系我。<br><br>"
            "</span>"
            "<span style='font-size: 22px; font-weight: bold;'>联系方式:</span><br>"
            "<span style='font-size: 20px;'>"
            "微信: 16673960116<br>"
            "邮箱: wntcy@163.com"
            "</span>"
        )
        
        # 使用垂直布局
        layout = QVBoxLayout()
        layout.addWidget(contact_label)
        contact_dialog.setLayout(layout)
        
        # 设置对话框样式
        contact_dialog.setStyleSheet("""
            QDialog {
                background-color: white;
            }
            QLabel {
                color: black;
                padding: 30px;
                line-height: 1.8;  /* 增加行间距 */
            }
        """)
        
        contact_dialog.exec_()

class FullScreenWindow(QWidget):
    def __init__(self):
        super().__init__()

        # 设置窗口标题和图标
        self.setWindowTitle('全屏录制')
        self.setWindowIcon(QIcon('icon.png'))

        # 创建时间显示标签
        self.elapsed_time_label = QLabel('用时间: 0秒', self)

        # 创建按钮
        self.start_button = QPushButton('开始录制', self)
        self.stop_button = QPushButton('停止录制', self)

        # 添加点击事件
        self.start_button.clicked.connect(self.start_recording)
        self.stop_button.clicked.connect(self.stop_recording)

        # 设置按钮和标签样式
        self.setStyleSheet("""
            QWidget {
                background-color: #000000;
            }
            QPushButton {
                background-color: #444444;
                color: white;
                border: none;
                font-size: 14px;
                min-height: 50px;
                min-width: 100px;
            }
            QPushButton:hover {
                background-color: #666666;
            }
            QLabel {
                color: white;
                font-size: 14px;
                min-height: 50px;
                min-width: 100px;
            }
        """)

        # 创建一行布局并添加组件
        layout = QHBoxLayout()
        layout.addWidget(self.elapsed_time_label)
        layout.addWidget(self.start_button)
        layout.addWidget(self.stop_button)
        self.setLayout(layout)
        self.setFixedSize(450, 100)

        self.recording = False
        self.total_seconds = 0
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update_time)

    def start_recording(self):
        if os.path.exists(AUDIO_FILENAME):
            os.remove(AUDIO_FILENAME)
        if os.path.exists(VIDEO_FILENAME):
            os.remove(VIDEO_FILENAME)

        self.recording = True
        self.start_button.setEnabled(False)
        self.stop_button.setEnabled(True)

        # 开启录制线程
        self.audio_thread = threading.Thread(target=self.record_audio)
        self.audio_thread.daemon = True
        self.audio_thread.start()

        self.video_thread = threading.Thread(target=self.record_video)
        self.video_thread.daemon = True
        self.video_thread.start()

        self.timer.start(1000)  # 开始计时器

    def stop_recording(self):
        self.recording = False
        self.timer.stop()  # 停止计时器

        if hasattr(self, 'audio_thread'):
            self.audio_thread.join()
        if hasattr(self, 'video_thread'):
            self.video_thread.join()

        try:
            if os.path.exists(VIDEO_FILENAME) and os.path.exists(AUDIO_FILENAME):
                video_clip = VideoFileClip(VIDEO_FILENAME)
                audio_clip = AudioFileClip(AUDIO_FILENAME)
                final_clip = video_clip.with_audio(audio_clip)

                save_path, _ = QFileDialog.getSaveFileName(self, '存视频', '', '视频文 (*.mp4)')
                if save_path:
                    final_clip.write_videofile(save_path, fps=FPS)
                    final_clip.close()  # 确保关闭 final_clip
                    video_clip.close()  # 确保关闭 video_clip
                    audio_clip.close()  # 确保关闭 audio_clip

                    os.remove(VIDEO_FILENAME)
                    os.remove(AUDIO_FILENAME)

                    # 临时清除样式表
                    self.setStyleSheet("")
                    QMessageBox.information(self, '录制完成', f'录制已完成视频路径为：\n{os.path.abspath(save_path)}')
                    # 恢复样式表
                    self.restore_stylesheet()
            else:
                self.setStyleSheet("")
                QMessageBox.warning(self, "错", "录制文件不存在，无法合。")
                self.restore_stylesheet()
        except Exception as e:
            self.setStyleSheet("")
            QMessageBox.warning(self, "错误", f"并和保存时错：{e}")
            self.restore_stylesheet()

        # 重新启用开始录制按钮
        self.start_button.setEnabled(True)
        self.stop_button.setEnabled(False)
        self.total_seconds = 0
        self.elapsed_time_label.setText('已用时间: 0秒')

    def restore_stylesheet(self):
        self.setStyleSheet("""
            QWidget {
                background-color: #000000;
            }
            QPushButton {
                background-color: #444444;
                color: white;
                border: none;
                font-size: 14px;
                min-height: 50px;
                min-width: 100px;
            }
            QPushButton:hover {
                background-color: #666666;
            }
            QLabel {
                color: white;
                font-size: 14px;
                min-height: 50px;
                min-width: 100px;
            }
        """)

    def record_audio(self):
        audio_frames = []
        try:
            p = pyaudio.PyAudio()

            stream = p.open(format=sample_format,
                            channels=CHANNELS,
                            rate=RATE,
                            frames_per_buffer=CHUNK,
                            input=True,
                            input_device_index=0)

            while self.recording:
                try:
                    data = stream.read(CHUNK)
                    audio_frames.append(data)
                except Exception as e:
                    print(f"音频制出错: {e}")
                    break
            stream.stop_stream()
            stream.close()
            p.terminate()

            # 将录制的音频保到文件
            wf = wave.open(AUDIO_FILENAME, 'wb')
            wf.setnchannels(CHANNELS)
            wf.setsampwidth(p.get_sample_size(sample_format))
            wf.setframerate(RATE)
            wf.writeframes(b''.join(audio_frames))
            wf.close()
        except Exception as e:
            QMessageBox.warning(self, "错误", f"音频初始化出错: {e}")

    def record_video(self):
        try:
            screen_size = pyautogui.size()  # 获屏幕分辨率
            fourcc = cv2.VideoWriter_fourcc(*"mp4v")
            out = cv2.VideoWriter(VIDEO_FILENAME, fourcc, FPS, screen_size)
            while self.recording:
                try:
                    img = pyautogui.screenshot()  # 获全屏
                    frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
                    out.write(frame)
                    QApplication.processEvents()
                except Exception as e:
                    print(f"视频录制出错: {e}")
                    break
            out.release()
        except Exception as e:
            QMessageBox.warning(self, "错误", f"视频始化出错：{e}")

    def update_time(self):
        if self.recording:
            self.total_seconds += 1
        time_str = QTime(0, 0, 0).addSecs(self.total_seconds).toString('hh:mm:ss')
        self.elapsed_time_label.setText(f"已用时间: {time_str}")

class ScreenshotWindow(QWidget):
    def __init__(self):
        super().__init__()

        self.setWindowTitle('区域录屏')
        self.setWindowIcon(QIcon('icon.png'))

        # 创建时间显示标签
        self.elapsed_time_label = QLabel('已用时间: 0秒', self)

        # 创建按钮
        self.capture_button = QPushButton('截取区域', self)
        self.start_button = QPushButton('开始录屏', self)
        self.stop_button = QPushButton('结束录屏', self)

        # 添加点击事件
        self.capture_button.clicked.connect(self.open_capture_dialog)
        self.start_button.clicked.connect(self.start_recording)
        self.stop_button.clicked.connect(self.stop_recording)

        # 设置按钮和标签样
        self.setStyleSheet("""
            QWidget {
                background-color: #000000;
            }
            QPushButton {
                background-color: #444444;
                color: white;
                border: none;
                font-size: 14px;
                min-height: 50px;
                min-width: 100px;
            }
            QPushButton:hover {
                background-color: #666666;
            }
            QLabel {
                color: white;
                font-size: 14px;
                min-height: 50px;
                min-width: 150px;
            }
        """)

        # 创建水平布局并添加组件
        layout = QHBoxLayout()
        layout.addWidget(self.elapsed_time_label)
        layout.addWidget(self.capture_button)
        layout.addWidget(self.start_button)
        layout.addWidget(self.stop_button)
        self.setLayout(layout)
        self.setFixedSize(600, 100)

        self.recording = False
        self.total_seconds = 0
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update_time)

        self.capture_area_defined = False
        self.capture_start = None
        self.capture_end = None

    def open_capture_dialog(self):
        dialog = CaptureDialog(self)
        
        # 临时清除应用程序的样式表
        QApplication.instance().setStyleSheet("")
        
        if dialog.exec_() == QDialog.Accepted:
            self.capture_start, self.capture_end = dialog.get_capture_area()
            self.capture_area_defined = True
            
            # 建 QMessageBox
            msg_box = QMessageBox(self)
            msg_box.setWindowTitle("区域选择")
            msg_box.setText("<font color='red'>域已记录<br>可以点击录制开始录制。</font>")
            
            # 设置标准按钮
            ok_button = msg_box.addButton(QMessageBox.Ok)
            ok_button.setText("确定")
            
            # 设置消息框的固定大小
            msg_box.setFixedSize(600, 200)  # 调整宽度和高度
            
            # 显示消息框
            msg_box.exec_()
        
        # 恢复样式表
        self.restore_stylesheet()

    def start_recording(self):
        if not self.capture_area_defined:
            QMessageBox.warning(self, "告", "请先选择截取区域。")
            return

        if os.path.exists(AUDIO_FILENAME):
            os.remove(AUDIO_FILENAME)
        if os.path.exists(VIDEO_FILENAME):
            os.remove(VIDEO_FILENAME)

        self.recording = True
        self.start_button.setEnabled(False)
        self.stop_button.setEnabled(True)

        # 开启录制线程
        self.audio_thread = threading.Thread(target=self.record_audio)
        self.audio_thread.daemon = True
        self.audio_thread.start()

        self.video_thread = threading.Thread(target=self.record_video)
        self.video_thread.daemon = True
        self.video_thread.start()

        self.timer.start(1000)  # 开始计时

    def stop_recording(self):
        self.recording = False
        self.timer.stop()  # 停止计器

        if hasattr(self, 'audio_thread'):
            self.audio_thread.join()
        if hasattr(self, 'video_thread'):
            self.video_thread.join()

        try:
            if os.path.exists(VIDEO_FILENAME) and os.path.exists(AUDIO_FILENAME):
                video_clip = VideoFileClip(VIDEO_FILENAME)
                audio_clip = AudioFileClip(AUDIO_FILENAME)
                final_clip = video_clip.with_audio(audio_clip)

                save_path, _ = QFileDialog.getSaveFileName(self, '保存视频', '', '视频文件 (*.mp4)')
                if save_path:
                    final_clip.write_videofile(save_path, fps=FPS)
                    final_clip.close()  # 确保关闭 final_clip
                    video_clip.close()  # 确保关闭 video_clip
                    audio_clip.close()  # 确保关闭 audio_clip

                    os.remove(VIDEO_FILENAME)
                    os.remove(AUDIO_FILENAME)

                    # 临时除样式表
                    self.setStyleSheet("")
                    QMessageBox.information(self, '录制完', f'录制已完成，视频路径为：\n{os.path.abspath(save_path)}')
                    # 恢复样式表
                    self.restore_stylesheet()
            else:
                self.setStyleSheet("")
                QMessageBox.warning(self, "错误", "制文件不存在，无法合并。")
                self.restore_stylesheet()
        except Exception as e:
            self.setStyleSheet("")
            QMessageBox.warning(self, "错误", f"合并和保存时出错：{e}")
            self.restore_stylesheet()

        # 重新启用开始录制按钮
        self.start_button.setEnabled(True)
        self.stop_button.setEnabled(False)
        self.total_seconds = 0
        self.elapsed_time_label.setText('已用时间: 0秒')

    def update_time(self):
        if self.recording:
            self.total_seconds += 1
        time_str = QTime(0, 0, 0).addSecs(self.total_seconds).toString('hh:mm:ss')
        self.elapsed_time_label.setText(f"已用时间: {time_str}")

    def restore_stylesheet(self):
        self.setStyleSheet("""
            QWidget {
                background-color: #000000;
            }
            QPushButton {
                background-color: #444444;
                color: white;
                border: none;
                font-size: 14px;
                min-height: 50px;
                min-width: 100px;
            }
            QPushButton:hover {
                background-color: #666666;
            }
            QLabel {
                color: white;
                font-size: 14px;
                min-height: 50px;
                min-width: 150px;
            }
        """)

    def record_video(self):
        try:
            # 算选取域宽度和高度
            x1, y1 = self.capture_start.x(), self.capture_start.y()
            x2, y2 = self.capture_end.x(), self.capture_end.y()
            width, height = abs(x2 - x1), abs(y2 - y1)

            fourcc = cv2.VideoWriter_fourcc(*"mp4v")
            out = cv2.VideoWriter(VIDEO_FILENAME, fourcc, FPS, (width, height))
            while self.recording:
                try:
                    img = pyautogui.screenshot(region=(x1, y1, width, height))  # 截取选定区域
                    frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
                    out.write(frame)
                    QApplication.processEvents()
                except Exception as e:
                    print(f"视频录制出错: {e}")
                    break
            out.release()
        except Exception as e:
            QMessageBox.warning(self, "错误", f"视频初始化出错：{e}")

    def record_audio(self):
        audio_frames = []
        try:
            p = pyaudio.PyAudio()

            stream = p.open(format=sample_format,
                            channels=CHANNELS,
                            rate=RATE,
                            frames_per_buffer=CHUNK,
                            input=True,
                            input_device_index=0)

            while self.recording:
                try:
                    data = stream.read(CHUNK)
                    audio_frames.append(data)
                except Exception as e:
                    print(f"音频录制出错: {e}")
                    break
            stream.stop_stream()
            stream.close()
            p.terminate()

            # 将录制的音频保存到文件
            wf = wave.open(AUDIO_FILENAME, 'wb')
            wf.setnchannels(CHANNELS)
            wf.setsampwidth(p.get_sample_size(sample_format))
            wf.setframerate(RATE)
            wf.writeframes(b''.join(audio_frames))
            wf.close()
        except Exception as e:
            QMessageBox.warning(self, "错误", f"音频初始化出错: {e}")

class CaptureDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle('选择截区域')
        # 修改窗口标志，确保窗口始终在最顶层
        self.setWindowFlags(
            Qt.FramelessWindowHint |  # 无框
            Qt.WindowStaysOnTopHint | # 总在最前
            Qt.Tool |                 # 工具窗口
            Qt.X11BypassWindowManagerHint  # X11下绕过窗口管理器
        )
        self.setWindowState(Qt.WindowFullScreen)
        self.setWindowOpacity(0.5)

        # 初始化其他属性
        self.start_pos = None
        self.end_pos = None
        self.current_rect = None
        self.dragging = False
        self.selection_completed = False
        
        # 设置标追踪
        self.setMouseTracking(True)
        
        # 确保对话框覆盖整个屏幕
        screen = QApplication.primaryScreen().geometry()
        self.setGeometry(screen)

        # 添加颜色选择相关属性
        self.current_color = Qt.black  # 默认黑色
        self.colors = [
            (Qt.black, "黑色"),
            (Qt.red, "红色"),
            (Qt.blue, "蓝色"),
            (Qt.green, "绿色"),
            (Qt.cyan, "青色"),
            (Qt.magenta, "紫色")
        ]

        # 创建内置的画笔图标
        self.pen_icon = self.create_pen_icon()
        self.pen_rect = None
        self.in_drawing_mode = False
        self.is_drawing = False
        self.drawing_points = []
        self.last_point = None

    def create_pen_icon(self):
        """创建一个更大的画笔图标"""
        # 增加图标尺寸
        icon = QPixmap(60, 60)
        icon.fill(Qt.transparent)
        
        painter = QPainter(icon)
        painter.setRenderHint(QPainter.Antialiasing)
        
        # 创建渐变
        gradient = QLinearGradient(0, 0, 60, 60)
        gradient.setColorAt(0, self.current_color)
        gradient.setColorAt(1, self.current_color)
        
        # 设置画笔和画刷
        painter.setPen(QPen(Qt.white, 2))  # 添加白色边框使图标更明显
        painter.setBrush(gradient)
        
        # 创建更大的箭头路径
        path = QPainterPath()
        path.moveTo(10, 50)
        path.cubicTo(20, 40, 25, 20, 40, 10)
        path.lineTo(50, 15)
        path.lineTo(35, 5)
        path.lineTo(30, 15)
        path.cubicTo(15, 25, 10, 40, 10, 50)
        
        # 添加阴影效果
        shadow = QPainterPath(path)
        shadow.translate(3, 3)
        painter.fillPath(shadow, QColor(0, 0, 0, 80))
        
        # 绘制主体
        painter.fillPath(path, gradient)
        painter.drawPath(path)  # 绘制白色边框
        
        painter.end()
        return icon

    def show_color_picker(self, pos):
        """显示颜色选择菜单"""
        menu = QMenu(self)
        menu.setStyleSheet("""
            QMenu {
                background-color: white;
                border: 1px solid #cccccc;
                padding: 5px;
            }
            QMenu::item {
                padding: 5px 30px 5px 30px;
                border: 1px solid transparent;
            }
            QMenu::item:selected {
                background-color: #e6e6e6;
            }
        """)

        for color, name in self.colors:
            action = QAction(name, self)
            # 创建颜色图标
            pixmap = QPixmap(20, 20)
            pixmap.fill(color)
            action.setIcon(QIcon(pixmap))
            action.triggered.connect(lambda checked, c=color: self.change_pen_color(c))
            menu.addAction(action)

        menu.exec_(pos)

    def change_pen_color(self, color):
        """改变画笔颜色"""
        self.current_color = color
        self.pen_icon = self.create_pen_icon()
        self.update()

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            if self.selection_completed:
                # 检查否点击了画笔按钮
                if self.pen_rect and self.pen_rect.contains(event.pos()):
                    self.show_color_picker(event.globalPos())
                    self.in_drawing_mode = True
                    return
                
                # 如果在绘模式
                if self.in_drawing_mode:
                    if self.current_rect.contains(event.pos()):
                        self.is_drawing = True
                        self.last_point = event.pos()
                        return
                else:
                    # 如果在选区内点击且不在绘画模式，直接截图
                    if self.current_rect.contains(event.pos()):
                        self.capture_and_copy()
                        return
                    else:
                        self.reject()
            else:
                # 开始新的选择
                self.start_pos = event.globalPos()
                self.current_rect = None
                self.dragging = True

    def mouseDoubleClickEvent(self, event):
        if event.button() == Qt.LeftButton and self.in_drawing_mode:
            self.capture_and_copy()

    def mouseMoveEvent(self, event):
        if self.dragging:
            self.end_pos = event.globalPos()
            self.current_rect = QRect(self.start_pos, self.end_pos)
            self.update()
        elif self.is_drawing and self.in_drawing_mode:
            # 添加新的绘画点
            self.drawing_points.append((self.last_point, event.pos()))
            self.last_point = event.pos()
            self.update()

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            if self.dragging:
                self.end_pos = event.globalPos()
                self.dragging = False
                self.selection_completed = True
                self.update()
            elif self.is_drawing:
                self.is_drawing = False

    def paintEvent(self, event):
        if self.current_rect:
            painter = QPainter(self)
            painter.setRenderHint(QPainter.Antialiasing)
            
            # 首先将整个窗口填充为半透明遮罩
            painter.fillRect(self.rect(), QColor(0, 0, 0, 128))  # 外部区域半透明遮罩
            
            # 清除选中区域的遮罩，使其完全透明
            painter.setCompositionMode(QPainter.CompositionMode_Clear)
            painter.fillRect(self.current_rect, Qt.transparent)
            
            # 恢复正常绘制模式
            painter.setCompositionMode(QPainter.CompositionMode_SourceOver)
            
            # 绘制选择框边框
            if self.selection_completed:
                painter.setPen(QPen(Qt.red, 3, Qt.SolidLine))
            else:
                painter.setPen(QPen(Qt.red, 1, Qt.SolidLine))
            painter.drawRect(self.current_rect)

            # 如果选择已完成，���制画笔按钮和提示
            if self.selection_completed:
                pen_text = "画笔"
                font = painter.font()
                font.setPointSize(12)
                font.setBold(True)
                painter.setFont(font)
                
                text_rect = painter.fontMetrics().boundingRect(pen_text)
                
                bg_rect = QRect(
                    self.current_rect.left() - text_rect.width() - 20,
                    self.current_rect.center().y() - text_rect.height() - 10,
                    text_rect.width() + 20,
                    text_rect.height() + 20
                )
                
                self.pen_rect = bg_rect
                
                painter.fillRect(bg_rect, QColor(0, 0, 0, 160))
                painter.setPen(Qt.white)
                painter.drawText(
                    bg_rect,
                    Qt.AlignCenter,
                    pen_text
                )

                if self.in_drawing_mode:
                    tip_text = "双击完成绘制"
                else:
                    tip_text = "点击画笔选择颜色开始绘制，选区内点击直接截图"
                
                font.setPointSize(10)
                painter.setFont(font)
                
                text_rect = painter.fontMetrics().boundingRect(tip_text)
                x = self.current_rect.center().x() - text_rect.width() / 2
                y = self.current_rect.bottom() + 20
                
                tip_bg_rect = QRect(
                    int(x - 10),
                    int(y - text_rect.height()),
                    text_rect.width() + 20,
                    text_rect.height() + 10
                )
                painter.fillRect(tip_bg_rect, QColor(0, 0, 0, 160))
                
                painter.setPen(Qt.white)
                painter.drawText(int(x), int(y), tip_text)

            # 绘制所有的涂鸦线条
            if self.drawing_points:
                painter.setPen(QPen(self.current_color, 3, Qt.SolidLine))
                for start, end in self.drawing_points:
                    painter.drawLine(start, end)

    def capture_and_copy(self):
        try:
            # 计算区域大小
            x1, y1 = min(self.start_pos.x(), self.end_pos.x()), min(self.start_pos.y(), self.end_pos.y())
            x2, y2 = max(self.start_pos.x(), self.end_pos.x()), max(self.start_pos.y(), self.end_pos.y())
            width = x2 - x1
            height = y2 - y1
            
            # 暂时隐藏窗口以获取原始截图
            self.hide()
            QApplication.processEvents()
            
            # 截取屏幕内容
            screen = QApplication.primaryScreen()
            screenshot = screen.grabWindow(0, x1, y1, width, height)
            
            # 将QPixmap转换为PIL Image
            buffer = QBuffer()
            buffer.open(QBuffer.ReadWrite)
            screenshot.save(buffer, "PNG")
            pil_image = Image.open(io.BytesIO(buffer.data()))
            
            # 调整亮度为1.5倍
            enhancer = ImageEnhance.Brightness(pil_image)
            brightened_image = enhancer.enhance(1.5)  # 从2.0改为1.5
            
            # PIL Image转回QPixmap
            buffer = io.BytesIO()
            brightened_image.save(buffer, format='PNG')
            adjusted_screenshot = QPixmap()
            adjusted_screenshot.loadFromData(buffer.getvalue())
            
            # 如果有涂鸦，将涂鸦绘制到截图上
            if self.drawing_points:
                painter = QPainter(adjusted_screenshot)
                painter.setPen(QPen(self.current_color, 3, Qt.SolidLine))
                for start, end in self.drawing_points:
                    adjusted_start = QPoint(start.x() - x1, start.y() - y1)
                    adjusted_end = QPoint(end.x() - x1, end.y() - y1)
                    painter.drawLine(adjusted_start, adjusted_end)
                painter.end()
            
            # 将截图复制到剪贴板
            QApplication.clipboard().setPixmap(adjusted_screenshot)
            
            # 关闭对话框
            self.accept()
            
            # 显示成功提示
            msg_box = QMessageBox(self.parent())
            msg_box.setWindowTitle("成功")
            msg_box.setText("<font color='black'>图片已复制到剪贴板</font>")
            msg_box.setIcon(QMessageBox.Information)
            msg_box.setWindowFlags(Qt.Dialog | Qt.WindowTitleHint | Qt.WindowCloseButtonHint)
            msg_box.setStyleSheet("""
                QMessageBox {
                    background-color: white;
                }
                QLabel {
                    background-color: white;
                    color: black;
                }
                QPushButton {
                    background-color: white;
                    border: 1px solid #cccccc;
                    padding: 5px 15px;
                    min-width: 80px;
                    color: black;
                }
                QPushButton:hover {
                    background-color: #f0f0f0;
                }
                QMessageBox QLabel#qt_msgboxex_icon_label { 
                    background-color: white;
                }
            """)
            msg_box.show()
            QTimer.singleShot(2000, msg_box.close)
            
        except Exception as e:
            QMessageBox.warning(self, "错误", f"截图失败：{str(e)}")

    def get_capture_area(self):
        return self.start_pos, self.end_pos

# 新增快捷键设置对话框类
class ShortcutSettingsDialog(QDialog):
    def __init__(self, parent=None):
        import json
        import os
        super().__init__(parent)
        self.setWindowTitle('快捷键设置')
        self.setFixedSize(400, 300)
        self.setWindowFlags(Qt.Dialog | Qt.WindowTitleHint | Qt.WindowCloseButtonHint)

        # 定义默认快捷键，使用更复杂的组合
        self.default_shortcuts = {
            'capture_screen': 'Ctrl+Alt+Q',  # 屏幕截取
            'full_screen': 'Ctrl+Alt+F',     # 全屏录制
            'area_record': 'Ctrl+Alt+A',     # 区域录制
            'game_record': 'Ctrl+Alt+G',     # 游戏录制
            'start_record': 'Ctrl+Alt+S',    # 开始录制
            'stop_record': 'Ctrl+Alt+X'      # 停止录制
        }

        # 创建布局
        layout = QVBoxLayout()

        # 创建快捷键设置项
        self.shortcut_items = [
            ('屏幕截取 (默认: Ctrl+Alt+Q)', 'capture_screen'),
            ('全屏录制 (默认: Ctrl+Alt+F)', 'full_screen'),
            ('区域录制 (默认: Ctrl+Alt+A)', 'area_record'),
            ('游戏录制 (默认: Ctrl+Alt+G)', 'game_record'),
            ('开始录制 (默认: Ctrl+Alt+S)', 'start_record'),
            ('停止录制 (默认: Ctrl+Alt+X)', 'stop_record')
        ]

        # 存储快键按钮的字典
        self.shortcut_buttons = {}

        # 为每个功能创建设置控件
        for label, key in self.shortcut_items:
            item_layout = QHBoxLayout()
            
            # 标签
            label_widget = QLabel(f"{label}:")
            label_widget.setFixedWidth(100)
            
            # 快捷键显示和编辑框
            shortcut_edit = QPushButton("点击设置快捷键")
            shortcut_edit.setObjectName(key)
            shortcut_edit.clicked.connect(self.start_shortcut_recording)
            
            # 保存按钮引用
            self.shortcut_buttons[key] = shortcut_edit
            
            # 读取已保存的快捷键
            saved_shortcut = self.load_shortcut(key)
            if saved_shortcut:
                shortcut_edit.setText(saved_shortcut)
            
            item_layout.addWidget(label_widget)
            item_layout.addWidget(shortcut_edit)
            layout.addLayout(item_layout)

        # 添加确定和取消按钮
        button_layout = QHBoxLayout()
        ok_button = QPushButton('确定')
        cancel_button = QPushButton('取消')
        
        ok_button.clicked.connect(self.accept)
        cancel_button.clicked.connect(self.reject)
        
        button_layout.addWidget(ok_button)
        button_layout.addWidget(cancel_button)
        layout.addLayout(button_layout)

        self.setLayout(layout)
        
        # 用于记录当正在设置快捷键的按钮
        self.current_recording_button = None

    def accept(self):
        """点确定按钮时的处理"""
        import json
        try:
            # 准备要保存的快捷键数据
            shortcuts_data = {}
            for key, button in self.shortcut_buttons.items():
                shortcut_text = button.text()
                if shortcut_text != "点击设置捷键" and shortcut_text != "请按下快捷键...":
                    shortcuts_data[key] = shortcut_text

            # 保存到文件
            config_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'shortcuts.json')
            with open(config_file, 'w', encoding='utf-8') as f:
                json.dump(shortcuts_data, f, ensure_ascii=True, indent=4)

            # 保存完成后，重新加载快捷键
            if isinstance(self.parent(), ScreenRecorderUI):
                self.parent().load_and_apply_shortcuts()

            # 显示保存成功的消息
            msg_box = QMessageBox(self)
            msg_box.setWindowTitle("成功")
            msg_box.setText("<font color='black'>快捷键设置已保存</font>")
            msg_box.setIcon(QMessageBox.Information)
            msg_box.setWindowFlags(Qt.Dialog | Qt.WindowTitleHint | Qt.WindowCloseButtonHint)
            msg_box.setStyleSheet("""
                QMessageBox {
                    background-color: white;
                }
                QLabel {
                    background-color: white;
                    color: black;
                }
                QPushButton {
                    background-color: white;
                    border: 1px solid #cccccc;
                    padding: 5px 15px;
                    min-width: 80px;
                    color: black;
                }
                QPushButton:hover {
                    background-color: #f0f0f0;
                }
                QMessageBox QLabel#qt_msgboxex_icon_label { 
                    background-color: white;
                }
            """)
            msg_box.exec_()

        except Exception as e:
            QMessageBox.warning(self, "错误", f"保存快捷键设置失败: {str(e)}")
            print(f"保存快捷键设置失败: {str(e)}")
            return

        super().accept()

    def load_shortcut(self, key):
        """加载快捷键设置"""
        import json
        try:
            config_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'shortcuts.json')
            if os.path.exists(config_file):
                with open(config_file, 'r', encoding='utf-8') as f:
                    shortcuts = json.load(f)
                    return shortcuts.get(key, '')
        except Exception as e:
            print(f"加载快捷键设置失败: {str(e)}")
        return ''

    def keyPressEvent(self, event):
        if self.current_recording_button:
            try:
                # 获取按下的按键组
                modifiers = event.modifiers()
                key = event.key()
                
                # 忽略单按下的修饰键
                if key in (Qt.Key_Control, Qt.Key_Alt, Qt.Key_Shift):
                    return
                
                # 构建快捷键文本
                keys = []
                if modifiers & Qt.ControlModifier:
                    keys.append("ctrl")  # 使用小写
                if modifiers & Qt.AltModifier:
                    keys.append("alt")   # 使用小写
                if modifiers & Qt.ShiftModifier:
                    keys.append("shift") # 用小写
                
                # 获取主键名称并转换写
                key_text = QKeySequence(key).toString().lower()
                if key_text and key_text != '':
                    keys.append(key_text)
                
                # 更新按钮文本
                if keys:
                    shortcut_text = "+".join(keys)
                    self.current_recording_button.setText(shortcut_text)
                    self.current_recording_button = None
                    event.accept()
                    return
                    
            except Exception as e:
                print(f"快捷键设置出错: {str(e)}")
                self.current_recording_button.setText("点击设置快捷键")
                self.current_recording_button = None
                
            super().keyPressEvent(event)

    def start_shortcut_recording(self):
        """开始记录快捷键"""
        sender = self.sender()
        if self.current_recording_button:
            # 如果之前有按钮在记录中，恢复其原始文本
            self.current_recording_button.setText(
                self.current_recording_button.property("original_text") or "点击设置快捷键"
            )
        
        # 保存当前按钮的原始文本
        sender.setProperty("original_text", sender.text())
        # 更改按钮文本提示用户输入
        sender.setText("请按下快捷键...")
        # 记录当前正在设置的按钮
        self.current_recording_button = sender

class RecordAreaSelector(QDialog):
    """专门用于区域录屏的区域选择器"""
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle('选择录制区域')
        self.setWindowFlags(
            Qt.FramelessWindowHint |
            Qt.WindowStaysOnTopHint
        )
        self.setAttribute(Qt.WA_TranslucentBackground)
        
        # 初始化属性
        self.start_pos = None
        self.end_pos = None
        self.current_rect = None
        self.selection_completed = False
        
        # 设置全屏
        screen = QApplication.primaryScreen().geometry()
        self.setGeometry(screen)
        self.setMouseTracking(True)

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        
        # 绘制半透明背景
        painter.fillRect(self.rect(), QColor(0, 0, 0, 128))
        
        if self.current_rect:
            # 清除选中区域的遮罩
            painter.setCompositionMode(QPainter.CompositionMode_Clear)
            painter.fillRect(self.current_rect, Qt.transparent)
            
            # 恢复正常绘制模式
            painter.setCompositionMode(QPainter.CompositionMode_SourceOver)
            
            # 绘制选择框边框
            if self.selection_completed:
                painter.setPen(QPen(Qt.blue, 2, Qt.SolidLine))  # 使用蓝色区分
            else:
                painter.setPen(QPen(Qt.blue, 1, Qt.SolidLine))
            painter.drawRect(self.current_rect)
            
            # 如果选择完成，显示提示
            if self.selection_completed:
                font = painter.font()
                font.setPointSize(10)
                painter.setFont(font)
                
                tip_text = "点击选区完成录制区域选择，ESC取消"
                text_rect = painter.fontMetrics().boundingRect(tip_text)
                x = self.current_rect.center().x() - text_rect.width() / 2
                y = self.current_rect.bottom() + 20
                
                # 绘制文本背景
                bg_rect = QRect(
                    int(x - 10),
                    int(y - text_rect.height()),
                    text_rect.width() + 20,
                    text_rect.height() + 10
                )
                painter.fillRect(bg_rect, QColor(0, 0, 0, 160))
                
                # 绘制文本
                painter.setPen(Qt.white)
                painter.drawText(int(x), int(y), tip_text)

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.start_pos = event.pos()
            self.current_rect = QRect()
            self.selection_completed = False
            self.update()

    def mouseMoveEvent(self, event):
        if self.start_pos and not self.selection_completed:
            self.end_pos = event.pos()
            self.current_rect = QRect(self.start_pos, self.end_pos).normalized()
            self.update()

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton and self.start_pos:
            self.end_pos = event.pos()
            self.current_rect = QRect(self.start_pos, self.end_pos).normalized()
            self.selection_completed = True
            self.update()
            
            # 如果在选区内点击，则确认选择
            if self.selection_completed and self.current_rect.contains(event.pos()):
                self.accept()

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Escape:
            self.reject()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    screen_recorder_ui = ScreenRecorderUI()
    screen_recorder_ui.show()
    sys.exit(app.exec_())